package cn.yhjz.platform.system.config.security;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

/**
 * 自定义身份验证类，spring security会自动调用此类的authenticate方法
 * 此处可以自定义身份验证的实现
 */
@Component
@Slf4j
public class SelfAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    /**
     * 登录的时候,springsecurity会调用此方法验证用户是否合法，开发者控制校验用户名和密码的逻辑。
     * 如果用户不存在，抛出BadCredentialsException
     * 如果验证成功，返回spring security的授权对象
     * @param authentication
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();
        String password = (String) authentication.getCredentials();
        UserDetails userdetails = userDetailsService.loadUserByUsername(username);
        if (userdetails == null) {
            //用户不存在
            throw new BadCredentialsException("用户名或密码错误");
        }
//        String p = bCryptPasswordEncoder.encode(password);
        //验证密码是否正确
        boolean passed = bCryptPasswordEncoder.matches(password, userdetails.getPassword());
        if (passed) {
            return new UsernamePasswordAuthenticationToken(userdetails, password, userdetails.getAuthorities());
        } else {
            throw new BadCredentialsException("用户名或密码错误");
        }
    }

    /**
     * 定义支持的权限认证类型，这里设置支持用户名和密码的类型
     *
     * @param authentication
     * @return
     */
    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}
